package com.dvj.demo.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMQConfig
 *
 * @author Dvj
 * @date 2021/7/1 17:32
 */
@Configuration
public class RabbitMQConfig {

    public static final String EXCHANGE_NAME = "boot_topic_exchange";
    public static final String QUEUE_NAME = "boot_queue";
    public static final String EXCHANGE_NAME_CONFIRM = "boot_exchange_confirm";
    public static final String QUEUE_NAME_CONFIRM = "boot_queue_confirm";
    public static final String EXCHANGE_NAME_QOS = "boot_exchange_qos";
    public static final String QUEUE_NAME_QOS = "boot_queue_qos";
    public static final String EXCHANGE_NAME_TTL = "boot_exchange_ttl";
    public static final String QUEUE_NAME_TTL = "boot_queue_ttl";

    /**
     * 1.交换机
     *
     * @return
     */
    @Bean("bootExchange")
    public Exchange bootExchange() {
        return ExchangeBuilder
                .topicExchange(EXCHANGE_NAME)
                .durable(true)
                .build();
    }

    /**
     * 2.Queue队列
     *
     * @return
     */
    @Bean("bootQueue")
    public Queue bootQueue() {
        return QueueBuilder
                .durable(QUEUE_NAME)
                .build();
    }

    /**
     * 3.队列合交换机绑定关系Binding
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding bindingQueueExchange(@Qualifier("bootQueue") Queue queue,
                                        @Qualifier("bootExchange") Exchange exchange) {
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("boot.#")
                .noargs();
    }

    /**
     * 消息可靠性投递的交换机
     *
     * @return
     */
    @Bean("bootExchangeConfirm")
    public Exchange bootExchangeConfirm() {
        return ExchangeBuilder
                .directExchange(EXCHANGE_NAME_CONFIRM)
                .durable(true)
                .build();
    }

    /**
     * 消息可靠性投递的队列
     *
     * @return
     */
    @Bean("bootQueueConfirm")
    public Queue bootQueueConfirm() {
        return QueueBuilder
                .durable(QUEUE_NAME_CONFIRM)
                .build();
    }

    /**
     * 消息可靠性投递的绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding bindingQueueExchangeConfirm(@Qualifier("bootQueueConfirm") Queue queue,
                                               @Qualifier("bootExchangeConfirm") Exchange exchange) {
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("confirm")
                .noargs();
    }

    /**
     * 限流交换机
     *
     * @return
     */
    @Bean("bootExchangeQos")
    public Exchange bootExchangeQos() {
        return ExchangeBuilder
                .directExchange(EXCHANGE_NAME_QOS)
                .durable(true)
                .build();
    }

    /**
     * 限流队列
     *
     * @return
     */
    @Bean("bootQueueQos")
    public Queue bootQueueQos() {
        return QueueBuilder
                .durable(QUEUE_NAME_QOS)
                .build();
    }

    /**
     * 限流队列与交换机绑定
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding bindingQueueExchangeQos(@Qualifier("bootQueueQos") Queue queue,
                                           @Qualifier("bootExchangeQos") Exchange exchange) {
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("qos")
                .noargs();
    }

    /**
     * TTL交换机
     *
     * @return
     */
    @Bean("bootExchangeTtl")
    public Exchange bootExchangeTtl() {
        return ExchangeBuilder
                .topicExchange(EXCHANGE_NAME_TTL)
                .durable(true)
                .build();
    }

    /**
     * TTL队列
     *
     * @return
     */
    @Bean("bootQueueTtl")
    public Queue bootQueueTtl() {
        return QueueBuilder
                .durable(QUEUE_NAME_TTL)
                .deadLetterExchange(EXCHANGE_NAME_DLX)
                .deadLetterRoutingKey("dlx.hh")
                .ttl(10000)
                .maxLength(10)
                .build();
    }

    /**
     * TTL队列与交换机绑定
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding bindingQueueExchangeTtl(@Qualifier("bootQueueTtl") Queue queue,
                                           @Qualifier("bootExchangeTtl") Exchange exchange) {
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("ttl.#")
                .noargs();
    }

    /*
     * 死信队列
     * 1.声明正常的队列(boot_queue)和交换机(boot_exchange),复用ttl
     * 2.声明死信队列(boot_queue_dlx)和死信交换机(boot_exchange_dlx)
     * 3.正常队列绑定死信交换机
     * 设置两个参数：
     *  * x-dead-letter-exchange：死信交换机名称
     *  * x-dead-routing-key：发送给死信交换机的routingKey
     * */

    public static final String EXCHANGE_NAME_DLX = "boot_exchange_dlx";
    public static final String QUEUE_NAME_DLX = "boot_queue_dlx";

    /**
     * 死信交换机
     *
     * @return
     */
    @Bean("bootExchangeDlx")
    public Exchange bootExchangeDlx() {
        return ExchangeBuilder
                .topicExchange(EXCHANGE_NAME_DLX)
                .durable(true)
                .build();
    }

    /**
     * 死信队列
     *
     * @return
     */
    @Bean("bootQueueDlx")
    public Queue bootQueueDlx() {
        return QueueBuilder
                .durable(QUEUE_NAME_DLX)
                .build();
    }

    /**
     * TTL队列与交换机绑定
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding bindingQueueExchangeDlx(@Qualifier("bootQueueDlx") Queue queue,
                                           @Qualifier("bootExchangeDlx") Exchange exchange) {
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("dlx.#")
                .noargs();
    }

}
